package service

import (
	"fmt"
	"strconv"
	"time"
	"usplatformserver/global"
	"usplatformserver/internal/model"
	"usplatformserver/internal/model/export"
	"usplatformserver/pkg/errcode"
	"usplatformserver/pkg/utils"

	"github.com/tealeg/xlsx"
)

type AnalysisStatisticsRequest struct {
	OrganType *int   `form:"organType" binding:"required,gte=0"`
	BeginTime string `form:"beginTime"`
	EndTime   string `form:"endTime"`
}

var analysisStatisticsSheetHeaders = []string{
	"指标名称", "TP", "ACC",
}

var statisticsCheckedCountSheetHeaders = []string{
	"日期", "患者数量", "甲状腺检查量", "乳腺检查量", "心脏检查量", "颈动脉检查量", "检查量合计",
}

func (svc *Service) GetAnalysisStatisticsData(organType int, patientsIds string) ([]*model.TargetInfo, int, error) {
	var pData []*model.TargetInfo = nil
	var checkedCount int = 0
	if organType == model.CheckpointThyroid {
		//获取统计数据
		tNidusList, err := svc.dao.GetThyroidExportData(patientsIds)
		if nil != err {
			return nil, checkedCount, errcode.ErrorGetAlgorithmStatDetailFail
		}
		if len(tNidusList) == 0 {
			return nil, checkedCount, nil
		}
		//获取AI统计数据
		tNidusAiList, err := svc.dao.GetThyroidExportDataAi(patientsIds)
		if nil != err {
			return nil, checkedCount, errcode.ErrorGetAlgorithmStatDetailFail
		}
		if len(tNidusAiList) == 0 {
			return nil, checkedCount, nil
		}
		//统计指标
		pData, checkedCount = statisticsThyroidData(tNidusList, tNidusAiList)
	} else if organType == model.CheckpointBreast {
		//获取分析数据
		tNidusList, err := svc.dao.GetBreastExportData(patientsIds)
		if nil != err {
			return nil, checkedCount, errcode.ErrorGetAlgorithmStatDetailFail
		}
		if len(tNidusList) == 0 {
			return nil, checkedCount, nil
		}
		//获取AI统计数据
		tNidusAiList, err := svc.dao.GetBreastExportDataAi(patientsIds)
		if nil != err {
			return nil, checkedCount, errcode.ErrorGetAlgorithmStatDetailFail
		}
		if len(tNidusAiList) == 0 {
			return nil, checkedCount, nil
		}
		//统计指标
		pData, checkedCount = statisticsBreastData(tNidusList, tNidusAiList)
	} else if organType == model.CheckpointCarotid {
		//获取分析数据
		tNidusList, err := svc.dao.GetCarotidExportData(patientsIds)
		if nil != err {
			return nil, checkedCount, errcode.ErrorGetAlgorithmStatDetailFail
		}
		if len(tNidusList) == 0 {
			return nil, checkedCount, nil
		}
		//获取AI统计数据
		tNidusAiList, err := svc.dao.GetCarotidExportDataAi(patientsIds)
		if nil != err {
			return nil, checkedCount, errcode.ErrorGetAlgorithmStatDetailFail
		}
		if len(tNidusAiList) == 0 {
			return nil, checkedCount, nil
		}
		//统计指标
		pData, checkedCount = statisticsCarotidData(tNidusList, tNidusAiList)
	}
	return pData, checkedCount, nil
}

func (svc *Service) ExportAnalysisStatisticsData(patientIds string) (string, error) {

	//创建excel文件
	file := xlsx.NewFile()

	//获取甲状腺病灶数据
	tNidusList, err := svc.dao.GetThyroidExportData(patientIds)
	if nil != err {
		return "", err
	}
	if len(tNidusList) == 0 {
		return "", nil
	}

	//获取AI病灶数据
	tNidusAiList, err := svc.dao.GetThyroidExportDataAi(patientIds)
	if nil != err {
		return "", err
	}

	//病灶数据添加至excel表格
	if len(tNidusList) > 0 {
		err = exportThyroid2Sheet(tNidusList, tNidusAiList, file)
		if nil != err {
			return "", err
		}
	}

	//甲状腺统计指标
	thyroidData, _ := statisticsThyroidData(tNidusList, tNidusAiList)
	//添加甲状腺统计指标
	if len(thyroidData) > 0 {
		err := addStatisticsSheet(file, thyroidData, "甲状腺统计指标")
		if err != nil {
			return "", err
		}
	}

	//获取乳腺病灶数据
	tbNidusList, err := svc.dao.GetBreastExportData(patientIds)
	if nil != err {
		return "", err
	}

	//获取AI病灶数据
	tbNidusAiList, err := svc.dao.GetBreastExportDataAi(patientIds)
	if nil != err {
		return "", err
	}

	//病灶数据添加至excel表格
	if len(tbNidusList) > 0 {
		err = exportBreast2Sheet(tbNidusList, tbNidusAiList, file)
		if nil != err {
			return "", err
		}
	}

	breastData, _ := statisticsBreastData(tbNidusList, tbNidusAiList)
	//添加乳腺统计指标
	if len(breastData) > 0 {
		err := addStatisticsSheet(file, breastData, "乳腺统计指标")
		if err != nil {
			return "", err
		}
	}

	//获取颈动脉病灶数据
	carotidNidusList, err := svc.dao.GetCarotidExportData(patientIds)
	if nil != err {
		return "", err
	}
	carotidNidusAiList, err := svc.dao.GetCarotidExportDataAi(patientIds)
	if nil != err {
		return "", err
	}
	//病灶数据添加至excel表格
	if len(carotidNidusList) > 0 {
		err = exportCarotid2Sheet(carotidNidusList, carotidNidusAiList, file)
		if nil != err {
			return "", err
		}
	}

	carotidData, _ := statisticsCarotidData(carotidNidusList, carotidNidusAiList)
	//添加颈动脉统计指标
	if len(carotidData) > 0 {
		err := addStatisticsSheet(file, carotidData, "颈动脉统计指标")
		if err != nil {
			return "", err
		}
	}

	fileName := fmt.Sprintf("statistics_%d.xlsx", time.Now().UnixMilli())
	err = file.Save(fileName)
	if err != nil {
		return "", err
	}

	return fileName, nil
}

func (svc *Service) GetHeartAnalysisStatisticsData(organType int, beginTime, endTime string) ([]*model.TargetInfoExt, error) {
	var pDataAll []*model.TargetInfoExt = nil
	//重组起始时间
	strBegin := fmt.Sprintf("%v 00:00:00", beginTime)
	//重组结束时间
	strEnd := fmt.Sprintf("%v 23:59:59", endTime)
	if organType == model.CheckpointHeart {
		//获取统计数据
		tNidusList, err := svc.dao.GetHeartMeasureData(strBegin, strEnd)
		if nil != err {
			return nil, errcode.ErrorGetHeartMeasureStatFail
		}
		//获取AI统计数据
		tNidusAiList, err := svc.dao.GetHeartMeasureDataAi(strBegin, strEnd)
		if nil != err {
			return nil, errcode.ErrorGetHeartMeasureStatFail
		}

		//统计指标
		pData1 := statisticsHeartMeasureData(tNidusList, tNidusAiList)

		//获取腔室统计数据
		tChamberData, err := svc.dao.GetChamberMeasureData(strBegin, strEnd)
		if nil != err {
			return nil, errcode.ErrorGetChamberMeasureStatFail
		}

		tChamberDataAi, err := svc.dao.GetChamberMeasureDataAi(strBegin, strEnd)
		if nil != err {
			return nil, errcode.ErrorGetChamberMeasureStatFail
		}

		//统计指标
		pData2, checkedCount, trueCheckedCount := statisticsChamberMeasureData(tChamberData, tChamberDataAi)

		//获取频谱统计数据
		tWaveformData, err := svc.dao.GetWaveformMeasureData(strBegin, strEnd)
		if nil != err {
			return nil, errcode.ErrorGetWaveformMeasureStatFail
		}
		tWaveformDataAi, err := svc.dao.GetWaveformMeasureDataAi(strBegin, strEnd)
		if nil != err {
			return nil, errcode.ErrorGetWaveformMeasureStatFail
		}

		pData3, wcheckedCount, wtrueCheckedCount := statisticsWaveformMeasureData(tWaveformData, tWaveformDataAi)
		fmt.Println("wcheckedCount: ", wcheckedCount, " checkedCount: ", checkedCount)
		//修改切面识别准确率
		if len(pData1) > 0 {
			pData1[0].CheckedCount = wcheckedCount + checkedCount
			pData1[0].TP = wtrueCheckedCount + trueCheckedCount
			if pData1[0].CheckedCount > 0 {
				accTmp := float32(pData1[0].TP) / float32(pData1[0].CheckedCount)
				pData1[0].ACC = getFloat32String(accTmp)
			}
		}
		fmt.Println("data3.len: ", len(pData3))

		pDataAll = append(pDataAll, pData1...)
		pDataAll = append(pDataAll, pData2...)
		pDataAll = append(pDataAll, pData3...)
	}
	return pDataAll, nil
}

// 统计甲状腺病灶数据
func statisticsThyroidData(ls, lsi []*export.ThyroidNidusInfo) ([]*model.TargetInfo, int) {
	var checkedCount int = 0
	var posTP int = 0
	var calcTP int = 0
	var coarseCalcTP = 0
	var peripheralCalcTP = 0
	var echoTP int = 0
	var solidTP int = 0
	var marginTP int = 0
	var directionTP int = 0
	var ctTP int = 0
	var acrtTP int = 0
	var ctlTP = 0
	var acrlTP int = 0
	//添加数据
	for i, v := range ls {
		// 已复核且未删除
		if v.CheckStatus == uint32(export.EChecked) && v.ImageIsDelete == 0 {
			checkedCount += 1
			if i >= len(lsi) {
				break
			}
			if v.Lobe == lsi[i].Lobe {
				posTP += 1
			}
			if v.EchogenicFoci == lsi[i].EchogenicFoci {
				calcTP += 1
			}
			if v.MacroCalcifications == lsi[i].MacroCalcifications {
				coarseCalcTP += 1
			}
			if v.PeripheralCalcifications == lsi[i].PeripheralCalcifications {
				peripheralCalcTP += 1
			}
			if v.Echogenic == lsi[i].Echogenic {
				echoTP += 1
			}
			if v.Solid == lsi[i].Solid {
				solidTP += 1
			}
			if v.Circumscribed == lsi[i].Circumscribed {
				marginTP += 1
			}
			if v.Tallerthanwide == lsi[i].Tallerthanwide {
				directionTP += 1
			}
			ctirads1 := getCTiradsValue(v)
			ctirads2 := getCTiradsValue(lsi[i])
			if ctirads1 == ctirads2 {
				ctTP += 1
			}
			acrtirads1 := getACRTiradsValue(v)
			acrtirads2 := getACRTiradsValue(lsi[i])
			if GetACRTiradsValueText(acrtirads1) == GetACRTiradsValueText(acrtirads2) {
				acrtTP += 1
			}
			cl1 := getTiradsLevel(ctirads1)
			cl2 := getTiradsLevel(ctirads2)
			if cl1 == cl2 {
				ctlTP += 1
			}
			acrl1 := getACRTiradsLevel(acrtirads1)
			acrl2 := getACRTiradsLevel(acrtirads2)
			if acrl1 == acrl2 {
				acrlTP += 1
			}

			fmt.Println("----------------------------------------")
			fmt.Println("acrtirads: ", acrtirads1, " ", acrtirads2)
			fmt.Println("实性: ", v.Solid, " ", lsi[i].Solid)
			fmt.Println("极低回声: ", v.Echogenic, " ", lsi[i].Echogenic)
			fmt.Println("微钙化: ", v.EchogenicFoci, " ", lsi[i].EchogenicFoci)
			fmt.Println("边缘: ", v.Circumscribed, " ", lsi[i].Circumscribed)
			fmt.Println("方位: ", v.Tallerthanwide, " ", lsi[i].Tallerthanwide)
			fmt.Println("----------------------------------------")
		}
	}

	fmt.Println("checkedCount: ", checkedCount)

	if checkedCount > 0 {
		pData := make([]*model.TargetInfo, 12)
		i := 0
		var accTmp float32 = 0
		//位置
		tmp := new(model.TargetInfo)
		tmp.TP = posTP
		accTmp = float32(posTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "位置"
		pData[i] = tmp
		i++

		//点状回声
		tmp = new(model.TargetInfo)
		tmp.TP = calcTP
		accTmp = float32(calcTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "点状回声"
		pData[i] = tmp
		i++
		//粗钙化
		tmp = new(model.TargetInfo)
		tmp.TP = coarseCalcTP
		accTmp = float32(coarseCalcTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "粗钙化"
		pData[i] = tmp
		i++
		//周边钙化
		tmp = new(model.TargetInfo)
		tmp.TP = peripheralCalcTP
		accTmp = float32(peripheralCalcTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "周边钙化"
		pData[i] = tmp
		i++
		//回声
		tmp = new(model.TargetInfo)
		tmp.TP = echoTP
		accTmp = float32(echoTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "回声"
		pData[i] = tmp
		i++
		//结构
		tmp = new(model.TargetInfo)
		tmp.TP = solidTP
		accTmp = float32(solidTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "结构"
		pData[i] = tmp
		i++
		//边缘
		tmp = new(model.TargetInfo)
		tmp.TP = marginTP
		accTmp = float32(marginTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "边缘"
		pData[i] = tmp
		i++
		//方位
		tmp = new(model.TargetInfo)
		tmp.TP = directionTP
		accTmp = float32(directionTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "方位"
		pData[i] = tmp
		i++
		//c-tirads
		tmp = new(model.TargetInfo)
		tmp.TP = ctTP
		accTmp = float32(ctTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "c-tirads"
		pData[i] = tmp
		i++
		//acr-tirads
		tmp = new(model.TargetInfo)
		tmp.TP = acrtTP
		accTmp = float32(acrtTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "acr-tirads"
		pData[i] = tmp
		i++
		//c-tirads风险等级
		tmp = new(model.TargetInfo)
		tmp.TP = ctlTP
		accTmp = float32(ctlTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "c-tirads风险等级"
		pData[i] = tmp
		i++
		//acr-tirads风险等级
		tmp = new(model.TargetInfo)
		tmp.TP = acrlTP
		accTmp = float32(acrlTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "acr-tirads风险等级"
		pData[i] = tmp
		fmt.Println("pData len: ", len(pData))
		return pData, checkedCount
	}

	return nil, checkedCount
}

// 统计乳腺病灶数据
func statisticsBreastData(ls, lsi []*export.BreastNidusInfo) ([]*model.TargetInfo, int) {
	var pData []*model.TargetInfo = nil
	var checkedCount int = 0
	var orientationTP int = 0
	var marginTP int = 0
	var echoTP = 0
	var shapeTP = 0
	var calcTP int = 0
	var acousticTP int = 0
	var glitchTP int = 0
	var vagueTP int = 0
	var mbTP int = 0
	var angledTP int = 0
	var hyperechoTP int = 0
	var biradsTP int = 0
	var biradsLevelTP int = 0
	//添加数据
	for i, v := range ls {
		// 已复核且未删除
		if v.CheckStatus == uint32(export.EChecked) && v.ImageIsDelete == 0 {
			checkedCount += 1
			if i >= len(lsi) {
				break
			}
			if v.Orientation == lsi[i].Orientation {
				orientationTP += 1
			}
			if v.Margin == lsi[i].Margin {
				marginTP += 1
			}
			if v.EchoGenicity == lsi[i].EchoGenicity {
				echoTP += 1
			}
			if v.Shape == lsi[i].Shape {
				shapeTP += 1
			}
			if v.MicroCalcifications == lsi[i].MicroCalcifications {
				calcTP += 1
			}
			if v.Acoustic == lsi[i].Acoustic {
				acousticTP += 1
			}
			if v.Glitch == lsi[i].Glitch {
				glitchTP += 1
			}
			if v.Vague == lsi[i].Vague {
				vagueTP += 1
			}
			if v.Microlobulation == lsi[i].Microlobulation {
				mbTP += 1
			}
			if v.Angled == lsi[i].Angled {
				angledTP += 1
			}
			if v.Hyperecho == lsi[i].Hyperecho {
				hyperechoTP += 1
			}
			btirads1 := getBTiradsValue(v)
			btirads2 := getBTiradsValue(lsi[i])
			if btirads1 == btirads2 {
				biradsTP += 1
			}
			bl1 := getTiradsLevel(btirads1)
			bl2 := getTiradsLevel(btirads2)
			if bl1 == bl2 {
				biradsLevelTP += 1
			}

			fmt.Println("----------------------------------------")
			fmt.Println("btirads: ", btirads1, " ", btirads2)
			fmt.Println("形状: ", v.Shape, " ", lsi[i].Shape)
			fmt.Println("微钙化: ", v.MicroCalcifications, " ", lsi[i].MicroCalcifications)
			fmt.Println("边缘: ", v.Margin, " ", lsi[i].Margin)
			fmt.Println("方位: ", v.Orientation, " ", lsi[i].Orientation)
			fmt.Println("----------------------------------------")
		}
	}

	if checkedCount > 0 {
		pData = make([]*model.TargetInfo, 13)
		i := 0
		//方位
		tmp := new(model.TargetInfo)
		tmp.TP = orientationTP
		accTmp := float32(orientationTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "方位"
		pData[i] = tmp
		i++
		//边缘
		tmp = new(model.TargetInfo)
		tmp.TP = marginTP
		accTmp = float32(marginTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "边缘"
		pData[i] = tmp
		i++
		//回声
		tmp = new(model.TargetInfo)
		tmp.TP = echoTP
		accTmp = float32(echoTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "回声"
		pData[i] = tmp
		i++
		//形状
		tmp = new(model.TargetInfo)
		tmp.TP = shapeTP
		accTmp = float32(shapeTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "形状"
		pData[i] = tmp
		i++
		//钙化
		tmp = new(model.TargetInfo)
		tmp.TP = calcTP
		accTmp = float32(calcTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "钙化"
		pData[i] = tmp
		i++
		//后方回声
		tmp = new(model.TargetInfo)
		tmp.TP = acousticTP
		accTmp = float32(acousticTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "后方回声"
		pData[i] = tmp
		i++
		//毛刺
		tmp = new(model.TargetInfo)
		tmp.TP = glitchTP
		accTmp = float32(glitchTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "毛刺"
		pData[i] = tmp
		i++
		//模糊
		tmp = new(model.TargetInfo)
		tmp.TP = vagueTP
		accTmp = float32(vagueTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "模糊"
		pData[i] = tmp
		i++
		//微小分叶
		tmp = new(model.TargetInfo)
		tmp.TP = mbTP
		accTmp = float32(mbTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "微小分叶"
		pData[i] = tmp
		i++
		//成角
		tmp = new(model.TargetInfo)
		tmp.TP = angledTP
		accTmp = float32(angledTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "成角"
		pData[i] = tmp
		i++
		//高回声晕
		tmp = new(model.TargetInfo)
		tmp.TP = hyperechoTP
		accTmp = float32(hyperechoTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "高回声晕"
		pData[i] = tmp
		i++
		//birads
		tmp = new(model.TargetInfo)
		tmp.TP = biradsTP
		accTmp = float32(biradsTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "birads"
		pData[i] = tmp
		i++
		//birads风险等级
		tmp = new(model.TargetInfo)
		tmp.TP = biradsLevelTP
		accTmp = float32(biradsLevelTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "birads风险等级"
		pData[i] = tmp
	}
	return pData, checkedCount
}

// 统计颈动脉病灶数据
func statisticsCarotidData(ls, lsi []*export.CarotidNidusInfo) ([]*model.TargetInfo, int) {
	var pData []*model.TargetInfo = nil
	var checkedCount int = 0
	var vdTP int = 0
	var bdTP int = 0
	var srTP = 0
	var hdTP = 0
	var echoTP int = 0
	var fcTP int = 0
	var edgeTP int = 0
	var calcTP int = 0
	var uclcerTP int = 0
	//添加数据
	for i, v := range ls {
		// 已复核且未删除
		if v.CheckStatus == uint32(export.EChecked) && v.ImageIsDelete == 0 {
			checkedCount += 1
			if i >= len(lsi) {
				break
			}
			if utils.IsRoughlyEqual(v.VerticalDiameter, lsi[i].VerticalDiameter) {
				vdTP += 1
			}
			if utils.IsRoughlyEqual(v.BloodDiameter, lsi[i].BloodDiameter) {
				bdTP += 1
			}
			if utils.IsRoughlyEqual(v.StenosisRate, lsi[i].StenosisRate) {
				srTP += 1
			}
			if utils.IsRoughlyEqual(v.HorizontalDiameter, lsi[i].HorizontalDiameter) {
				hdTP += 1
			}
			if v.Echogenicity == lsi[i].Echogenicity && v.EchogenicityGrade == lsi[i].EchogenicityGrade {
				echoTP += 1
			}
			if v.FibrousCap == lsi[i].FibrousCap {
				fcTP += 1
			}
			if v.Edge == lsi[i].Edge {
				edgeTP += 1
			}
			if v.Calcification == lsi[i].Calcification {
				calcTP += 1
			}
			if v.Uclcer == lsi[i].Uclcer {
				uclcerTP += 1
			}

			fmt.Println("----------------------------------------")
			fmt.Println("斑块厚度: ", v.VerticalDiameter, " ", lsi[i].VerticalDiameter)
			fmt.Println("管腔内径: ", v.BloodDiameter, " ", lsi[i].BloodDiameter)
			fmt.Println("狭窄率: ", v.StenosisRate, " ", lsi[i].StenosisRate)
			fmt.Println("斑块长度: ", v.HorizontalDiameter, " ", lsi[i].HorizontalDiameter)
			fmt.Println("纤维帽: ", v.FibrousCap, " ", lsi[i].FibrousCap)
			fmt.Println("----------------------------------------")
		}
	}

	if checkedCount > 0 {
		pData = make([]*model.TargetInfo, 9)
		i := 0
		//斑块厚度
		tmp := new(model.TargetInfo)
		tmp.TP = vdTP
		accTmp := float32(vdTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "斑块厚度"
		pData[i] = tmp
		i++
		//管腔内径
		tmp = new(model.TargetInfo)
		tmp.TP = bdTP
		accTmp = float32(bdTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "管腔内径"
		pData[i] = tmp
		i++
		//狭窄率
		tmp = new(model.TargetInfo)
		tmp.TP = srTP
		accTmp = float32(srTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "狭窄率"
		pData[i] = tmp
		i++
		//斑块长度
		tmp = new(model.TargetInfo)
		tmp.TP = hdTP
		accTmp = float32(hdTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "斑块长度"
		pData[i] = tmp
		i++
		//回声
		tmp = new(model.TargetInfo)
		tmp.TP = echoTP
		accTmp = float32(echoTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "回声"
		pData[i] = tmp
		i++
		//纤维帽
		tmp = new(model.TargetInfo)
		tmp.TP = fcTP
		accTmp = float32(fcTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "纤维帽"
		pData[i] = tmp
		i++
		//边缘
		tmp = new(model.TargetInfo)
		tmp.TP = edgeTP
		accTmp = float32(edgeTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "边缘"
		pData[i] = tmp
		i++
		//钙化
		tmp = new(model.TargetInfo)
		tmp.TP = calcTP
		accTmp = float32(calcTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "钙化"
		pData[i] = tmp
		i++
		//溃疡
		tmp = new(model.TargetInfo)
		tmp.TP = uclcerTP
		accTmp = float32(uclcerTP) / float32(checkedCount)
		tmp.ACC = getFloat32String(accTmp)
		tmp.Code = "溃疡"
		pData[i] = tmp
	}
	return pData, checkedCount
}

func getTiradsLevel(ctirads int) string {
	cl := "低风险"
	if ctirads > 0 {
		cl = "高风险"
	}
	return cl
}

func getACRTiradsLevel(acrtirads int) string {
	acrl := "低风险"
	if acrtirads > 3 {
		acrl = "高风险"
	}
	return acrl
}

func addStatisticsSheet(file *xlsx.File, data []*model.TargetInfo, sheetName string) error {
	//添加表
	sheet, err := file.AddSheet(sheetName)
	if nil != err {
		return err
	}
	//添加标题行
	row := sheet.AddRow()
	//添加列标
	for _, v := range analysisStatisticsSheetHeaders {
		cell := row.AddCell()
		cell.Value = v
	}

	//添加数据
	for _, v := range data {
		row := sheet.AddRow()
		//位置
		appendCell(row, v.Code)
		//TP
		appendCell(row, fmt.Sprintf("%v ", v.TP))
		//ACC
		appendCell(row, fmt.Sprintf("%v", v.ACC))
	}
	return nil
}

// 导出甲状腺病灶数据至excel表格
func exportThyroid2Sheet(ls, lsi []*export.ThyroidNidusInfo, file *xlsx.File) error {

	//添加表
	sheet, err := file.AddSheet("甲状腺病灶数据")
	if err != nil {
		return err
	}
	//添加标题行
	row := sheet.AddRow()
	//添加列标
	for _, v := range thyroidSheetHeaders {
		cell := row.AddCell()
		cell.Value = v
	}

	//添加数据
	for i, v := range ls {
		appendThyroidExcelRow(sheet, v, getCheckStatusString(v.CheckStatus))
		if i < len(lsi) {
			//修改数据后跟一条AI原始数据
			appendThyroidExcelRow(sheet, lsi[i], "AI")
		}
	}

	return nil
}

// 导出乳腺病灶数据至excel表格
func exportBreast2Sheet(ls, lsi []*export.BreastNidusInfo, file *xlsx.File) error {
	//添加表
	sheet, err := file.AddSheet("乳腺病灶数据")
	if err != nil {
		return err
	}
	//添加标题行
	row := sheet.AddRow()
	//添加列标
	for _, v := range breastSheetHeaders {
		cell := row.AddCell()
		cell.Value = v
	}

	//添加数据
	for i, v := range ls {
		appendBreastExcelRow(sheet, v, getCheckStatusString(v.CheckStatus))
		if i < len(lsi) {
			appendBreastExcelRow(sheet, lsi[i], "AI")
		}
	}

	return nil
}

// 导出颈动脉病灶数据至excel表格
func exportCarotid2Sheet(ls, lsi []*export.CarotidNidusInfo, file *xlsx.File) error {
	//添加表
	sheet, err := file.AddSheet("颈动脉病灶数据")
	if err != nil {
		return err
	}
	//添加标题行
	row := sheet.AddRow()
	//添加列标
	for _, v := range carotidSheetHeaders {
		cell := row.AddCell()
		cell.Value = v
	}

	//添加数据
	for i, v := range ls {
		appendCarotidExcelRow(sheet, v, getCheckStatusString(v.CheckStatus))
		if i < len(lsi) {
			appendCarotidExcelRow(sheet, lsi[i], "AI")
		}
	}

	return nil
}

func (svc *Service) StatisticsCheckedCount(beginTime, endTime string) ([]*model.CheckedCountList, error) {
	//重组起始时间
	strBegin := reCombinationDateTime(beginTime, "000000")
	//重组结束时间
	strEnd := reCombinationDateTime(endTime, "235959")
	// 获取检查总数
	var checkedOrganCountList []*model.CheckedOrganCount
	checkedOrganCountList, err := svc.dao.StatisticsCheckedOrganCountList(strBegin, strEnd)
	if err != nil {
		global.Logger.Infof("statisticsOrganCountList error: %v", err.Error())
		return nil, err
	}

	//获取患者总数
	var checkedPatientCountList []*model.CheckedPatientCount
	checkedPatientCountList, err = svc.dao.StatisticsCheckedPatientCountList(strBegin, strEnd)
	if err != nil {
		global.Logger.Infof("statisticsPatientCountList error: %v", err.Error())
		return nil, err
	}

	//检查总数
	var checkedList []*model.CheckedCountList

	for _, v1 := range checkedPatientCountList {
		checkedDate1, _ := time.Parse("2006-01-02T15:04:05+08:00", v1.Date)
		checkedCount := new(model.CheckedCountList)
		checkedCount.Date = checkedDate1.Format("2006-01-02")
		checkedCount.PatientCount = v1.Count
		for _, v2 := range checkedOrganCountList {
			date2, _ := time.Parse("2006-01-02T15:04:05+08:00", v2.Date)
			fmt.Println(date2)
			if checkedCount.Date == date2.Format("2006-01-02") {
				checkedCount.CheckedOrganCountList = append(checkedCount.CheckedOrganCountList, v2)
				checkedCount.CheckedCount += v2.Count
			}
		}
		checkedList = append(checkedList, checkedCount)
	}
	fmt.Println("checkedList.count: ", len(checkedList))

	return checkedList, nil
}

func (svc *Service) ExportStatisticsCheckedCount(beginTime, endTime string) (string, error) {
	//重组起始时间
	strBegin := reCombinationDateTime(beginTime, "000000")
	//重组结束时间
	strEnd := reCombinationDateTime(endTime, "235959")
	// 获取检查总数
	var checkedOrganCountList []*model.CheckedOrganCount
	checkedOrganCountList, err := svc.dao.StatisticsCheckedOrganCountList(strBegin, strEnd)
	if err != nil {
		global.Logger.Infof("statisticsOrganCountList error: %v", err.Error())
		return "", err
	}

	//获取患者总数
	var checkedPatientCountList []*model.CheckedPatientCount
	checkedPatientCountList, err = svc.dao.StatisticsCheckedPatientCountList(strBegin, strEnd)
	if err != nil {
		global.Logger.Infof("statisticsPatientCountList error: %v", err.Error())
		return "", err
	}

	return exportCheckedData(checkedPatientCountList, checkedOrganCountList)
}

func exportCheckedData(checkedPatientCount []*model.CheckedPatientCount, checkedOrganCount []*model.CheckedOrganCount) (string, error) {
	//创建excel文件
	file := xlsx.NewFile()

	//添加表
	sheet, err := file.AddSheet("检查量统计")
	if err != nil {
		return "", err
	}
	//添加标题行
	row := sheet.AddRow()
	//添加列标
	for _, v := range statisticsCheckedCountSheetHeaders {
		cell := row.AddCell()
		cell.Value = v
	}

	//导出数据
	pCount := 0
	tCount := 0
	bCount := 0
	hCount := 0
	cCount := 0
	ccCount := 0
	for _, v1 := range checkedPatientCount {
		row := sheet.AddRow()
		checkedDate1, _ := time.Parse("2006-01-02T15:04:05+08:00", v1.Date)
		//日期
		cell1 := row.AddCell()
		cell1.Value = checkedDate1.Format("2006-01-02")
		//患者数量
		cell2 := row.AddCell()
		cell2.Value = strconv.Itoa(v1.Count)
		pCount += v1.Count
		//甲状腺检查量
		cell3 := row.AddCell()
		cell3.Value = "0"
		//乳腺检查量
		cell4 := row.AddCell()
		cell4.Value = "0"
		//心脏检查量
		cell5 := row.AddCell()
		cell5.Value = "0"
		//颈动脉检查量
		cell6 := row.AddCell()
		cell6.Value = "0"
		//检查量合计
		cell7 := row.AddCell()
		checkedCount := 0
		for _, v2 := range checkedOrganCount {
			date2, _ := time.Parse("2006-01-02T15:04:05+08:00", v2.Date)
			fmt.Println(date2)
			if checkedDate1.Format("2006-01-02") == date2.Format("2006-01-02") {
				if v2.OrganType == model.CheckpointThyroid {
					cell3.Value = strconv.Itoa(v2.Count)
					tCount += v2.Count
				} else if v2.OrganType == model.CheckpointBreast {
					cell4.Value = strconv.Itoa(v2.Count)
					bCount += v2.Count
				} else if v2.OrganType == model.CheckpointHeart {
					cell5.Value = strconv.Itoa(v2.Count)
					hCount += v2.Count
				} else if v2.OrganType == model.CheckpointCarotid {
					cell6.Value = strconv.Itoa(v2.Count)
					cCount += v2.Count
				}
				checkedCount += v2.Count
			}
		}
		cell7.Value = strconv.Itoa(checkedCount)
		ccCount += checkedCount
	}

	//添加合计行
	row = sheet.AddRow()
	appendCell(row, "合计")
	appendCell(row, strconv.Itoa(pCount))
	appendCell(row, strconv.Itoa(tCount))
	appendCell(row, strconv.Itoa(bCount))
	appendCell(row, strconv.Itoa(hCount))
	appendCell(row, strconv.Itoa(cCount))
	appendCell(row, strconv.Itoa(ccCount))

	fileName := "checkedCount.xlsx"
	err = file.Save(fileName)
	if err != nil {
		return "", err
	}

	return fileName, nil
}

func statisticsHeartMeasureData(ls, lsi []*export.HeartMeasureData) []*model.TargetInfoExt {
	chamberTP := 0
	chamberCheckedCount := 0
	chamberType := 0
	patientId := 0
	LVEFSimpsonCheckedCount := 0
	LVEFSimpsonTP := 0
	LVEFA2CCheckedCount := 0
	LVEFA2C := 0
	LVEFA3CCheckedCount := 0
	LVEFA3C := 0
	LVEFA4CCheckedCount := 0
	LVEFA4C := 0
	LVEFPLVCheckedCount := 0
	LVEFPLV := 0

	for i, v := range ls {
		if chamberType != v.ChamberType || patientId != v.PatientId {
			patientId = v.PatientId
			chamberType = v.ChamberType
			chamberCheckedCount += 1
			chamberTP += 1
			if v.ChamberType == model.ChamberType2 {
				LVEFA2CCheckedCount += 1
				if v.LVEFSimpson > 0.001 {
					LVEFSimpsonCheckedCount += 1
				}
			} else if v.ChamberType == model.ChamberType3 {
				LVEFA3CCheckedCount += 1
			} else if v.ChamberType == model.ChamberType4 {
				LVEFA4CCheckedCount += 1
			} else if v.ChamberType == model.ChamberTypePLV {
				LVEFPLVCheckedCount += 1
			}

			if i < len(lsi) {
				if utils.IsRoughlyEqual(v.LVEFSimpson, lsi[i].LVEFSimpson) {
					if v.ChamberType == model.ChamberType2 {
						LVEFSimpsonTP += 1
					}
				}
				if utils.IsRoughlyEqual(v.LVEF, lsi[i].LVEF) {
					if v.ChamberType == model.ChamberType2 {
						LVEFA2C += 1
					} else if v.ChamberType == model.ChamberType3 {
						LVEFA3C += 1
					} else if v.ChamberType == model.ChamberType4 {
						LVEFA4C += 1
					} else if v.ChamberType == model.ChamberTypePLV {
						LVEFPLV += 1
					}
				}
			}
		}
	}

	var ret []*model.TargetInfoExt = make([]*model.TargetInfoExt, 6)

	//切面识别准确率
	tmp := new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = chamberTP
	accTmp := float32(0)
	if chamberCheckedCount > 0 {
		accTmp = float32(chamberTP) / float32(chamberCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = chamberCheckedCount
	tmp.Code = "切面识别准确率"
	ret[0] = tmp

	//LVEF(Simpson)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = LVEFSimpsonTP
	accTmp = 0
	if LVEFSimpsonCheckedCount > 0 {
		accTmp = float32(LVEFSimpsonTP) / float32(LVEFSimpsonCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = LVEFSimpsonCheckedCount
	tmp.Code = "LVEF(Simpson)"
	ret[1] = tmp

	//LVEF(A2C)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = LVEFA2C
	accTmp = 0
	if LVEFA2CCheckedCount > 0 {
		accTmp = float32(LVEFA2C) / float32(LVEFA2CCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = LVEFA2CCheckedCount
	tmp.Code = "LVEF(A2C)"
	ret[2] = tmp

	//LVEF(A3C)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = LVEFA3C
	accTmp = 0
	if LVEFA3CCheckedCount > 0 {
		accTmp = float32(LVEFA3C) / float32(LVEFA3CCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = LVEFA3CCheckedCount
	tmp.Code = "LVEF(A3C)"
	ret[3] = tmp

	//LVEF(A4C)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = LVEFA4C
	accTmp = 0
	if LVEFA4CCheckedCount > 0 {
		accTmp = float32(LVEFA4C) / float32(LVEFA4CCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = LVEFA4CCheckedCount
	tmp.Code = "LVEF(A4C)"
	ret[4] = tmp

	//LVEF(PLV)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = LVEFPLV
	accTmp = 0
	if LVEFPLVCheckedCount > 0 {
		accTmp = float32(LVEFPLV) / float32(LVEFPLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = LVEFPLVCheckedCount
	tmp.Code = "LVEF(PLV)"
	ret[5] = tmp

	return ret
}

func statisticsChamberMeasureData(ls, lsi []*export.ChamberMeasureData) ([]*model.TargetInfoExt, int, int) {
	chamberType := 0
	patientId := 0
	imageType := 0
	PLVCheckedCount := 0
	PSACheckedCount := 0
	checkedCount := 0
	trueCheckedCount := 0
	aodd := 0
	ivst := 0
	lads := 0
	lvpwt := 0
	lvdd := 0
	lvds := 0
	lvad := 0
	lvas := 0
	padd := 0

	for i, v := range ls {
		fmt.Println("v.chamberType: ", v.ChamberType, " v.PatientId: ", v.PatientId, " v.ImageType: ", v.ImageType)
		if v.Period > 0 {
			if chamberType != v.ChamberType || patientId != v.PatientId || imageType != v.ImageType {
				checkedCount += 1
				chamberType = v.ChamberType
				patientId = v.PatientId
				imageType = v.ImageType
				if v.ChamberType == v.CheckedType {
					trueCheckedCount += 1
				}
				if v.ChamberType == model.ChamberTypePLV {
					PLVCheckedCount += 1
				} else if v.ChamberType == model.ChamberTypePSA {
					PSACheckedCount += 1
				}
			}
			if v.ChamberType == model.ChamberTypePLV {
				if i < len(lsi) {
					if v.Period == model.PeriodDiastolic {
						if utils.IsRoughlyEqual(v.AoDiameter, lsi[i].AoDiameter) {
							aodd += 1
						}
						if utils.IsRoughlyEqual(v.Ivst, lsi[i].Ivst) {
							ivst += 1
						}
						if utils.IsRoughlyEqual(v.Lvpwt, lsi[i].Lvpwt) {
							lvpwt += 1
						}
						if utils.IsRoughlyEqual(v.LvDiameter, lsi[i].LvDiameter) {
							lvdd += 1
						}
						if utils.IsRoughlyEqual(v.Area, lsi[i].Area) {
							lvad += 1
						}
					} else if v.Period == model.PeriodSystole {
						if utils.IsRoughlyEqual(v.LaDiameter, lsi[i].LaDiameter) {
							lads += 1
						}
						if utils.IsRoughlyEqual(v.LvDiameter, lsi[i].LvDiameter) {
							lvds += 1
						}
						if utils.IsRoughlyEqual(v.Area, lsi[i].Area) {
							lvas += 1
						}
					}
				}
			} else if v.ChamberType == model.ChamberTypePSA {
				if v.Period == model.PeriodSystole {
					if utils.IsRoughlyEqual(v.Padd, lsi[i].Padd) {
						padd += 1
					}
				}
			}
		}
	}

	fmt.Println("PLVCheckedCount: ", PLVCheckedCount)

	var ret []*model.TargetInfoExt = make([]*model.TargetInfoExt, 9)

	//AODd(PLV)
	tmp := new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = aodd
	accTmp := float32(0)
	if PLVCheckedCount > 0 {
		accTmp = float32(aodd) / float32(PLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PLVCheckedCount
	tmp.Code = "AODd(PLV)"
	ret[0] = tmp

	//IVST(PLV)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = ivst
	accTmp = 0
	if PLVCheckedCount > 0 {
		accTmp = float32(ivst) / float32(PLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PLVCheckedCount
	tmp.Code = "IVST(PLV)"
	ret[1] = tmp

	//LADs(PLV)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = lads
	accTmp = 0
	if PLVCheckedCount > 0 {
		accTmp = float32(lads) / float32(PLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PLVCheckedCount
	tmp.Code = "LADs(PLV)"
	ret[2] = tmp

	//LVPWT(PLV)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = lvpwt
	accTmp = 0
	if PLVCheckedCount > 0 {
		accTmp = float32(lvpwt) / float32(PLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PLVCheckedCount
	tmp.Code = "LVPWT(PLV)"
	ret[3] = tmp

	//LVDd(PLV)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = lvdd
	accTmp = 0
	if PLVCheckedCount > 0 {
		accTmp = float32(lvdd) / float32(PLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PLVCheckedCount
	tmp.Code = "LVDd(PLV)"
	ret[4] = tmp

	//LVDs(PLV)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = lvds
	accTmp = 0
	if PLVCheckedCount > 0 {
		accTmp = float32(lvds) / float32(PLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PLVCheckedCount
	tmp.Code = "LVDs(PLV)"
	ret[5] = tmp

	//LVAd(PLV)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = lvad
	accTmp = 0
	if PLVCheckedCount > 0 {
		accTmp = float32(lvad) / float32(PLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PLVCheckedCount
	tmp.Code = "LVAd(PLV)"
	ret[6] = tmp

	//LVAs(PLV)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = lvas
	accTmp = 0
	if PLVCheckedCount > 0 {
		accTmp = float32(lvas) / float32(PLVCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PLVCheckedCount
	tmp.Code = "LVAs(PLV)"
	ret[7] = tmp

	//PADd(PSA)
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = padd
	accTmp = 0
	if PSACheckedCount > 0 {
		accTmp = float32(padd) / float32(PSACheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = PSACheckedCount
	tmp.Code = "PADd(PSA)"
	ret[8] = tmp

	return ret, checkedCount, trueCheckedCount
}

func statisticsWaveformMeasureData(ls, lsi []*export.WaveformMeasureData) ([]*model.TargetInfoExt, int, int) {
	eaCheckedCount := 0
	epCheckedCount := 0
	tdisCheckedCount := 0
	tapseCheckedCount := 0
	checkedCount := 0
	trueCheckedCount := 0
	ea := 0
	ep := 0
	tdis := 0
	tapse := 0

	for i, v := range ls {
		fmt.Println("v.Period: ", v.Period, " v.CheckedType: ", v.CheckedType)
		if v.CheckedType > 0 && i < len(lsi) {
			checkedCount += 1
			if v.Period == v.CheckedType {
				trueCheckedCount += 1
			}
			if v.Period == model.PeriodEA {
				eaCheckedCount += 1
				eaValue := v.VelE / v.VelA
				eaValue1 := lsi[i].VelE / lsi[i].VelA
				if utils.IsRoughlyEqual(eaValue, eaValue1) {
					ea += 1
				}
			} else if v.Period == model.PeriodEP {
				epCheckedCount += 1
				if utils.IsRoughlyEqual(v.Velep, lsi[i].Velep) {
					ep += 1
				}
			} else if v.Period == model.PeriodTdis {
				tdisCheckedCount += 1
				if utils.IsRoughlyEqual(v.TDIS, lsi[i].TDIS) {
					tdis += 1
				}
			} else if v.Period == model.PeriodTapse {
				tapseCheckedCount += 1
				if utils.IsRoughlyEqual(v.TAPSE, lsi[i].TAPSE) {
					tapse += 1
				}
			}
		}
	}

	var ret []*model.TargetInfoExt = make([]*model.TargetInfoExt, 4)

	//E/A
	tmp := new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = ea
	accTmp := float32(0)
	if eaCheckedCount > 0 {
		accTmp = float32(ea) / float32(eaCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = eaCheckedCount
	tmp.Code = "E/A"
	ret[0] = tmp

	//e'
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = ep
	accTmp = 0
	if epCheckedCount > 0 {
		accTmp = float32(ep) / float32(epCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = epCheckedCount
	tmp.Code = "e'"
	ret[1] = tmp

	//TDIs'
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = tdis
	accTmp = 0
	if tdisCheckedCount > 0 {
		accTmp = float32(tdis) / float32(tdisCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = tdisCheckedCount
	tmp.Code = "TDIs'"
	ret[2] = tmp

	//TAPSE
	tmp = new(model.TargetInfoExt)
	tmp.TargetInfo = new(model.TargetInfo)
	tmp.TP = tapse
	accTmp = 0
	if tapseCheckedCount > 0 {
		accTmp = float32(tapse) / float32(tapseCheckedCount)
	}
	tmp.ACC = getFloat32String(accTmp)
	tmp.CheckedCount = tapseCheckedCount
	tmp.Code = "TAPSE"
	ret[3] = tmp

	return ret, checkedCount, trueCheckedCount
}
